package com.ling.module1sbbyyds.utils;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.oss20190517.AsyncClient;
import com.aliyun.sdk.service.oss20190517.models.HeadObjectRequest;
import com.aliyun.sdk.service.oss20190517.models.HeadObjectResponse;
import com.aliyun.sdk.service.oss20190517.models.PutObjectRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.ling.sbbyyds.entity.community.ImagesMd5;
import com.ling.sbbyyds.mapper.community.ImageMd5Mapper;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 天道酬勤、学无止境
 *
 * @Description: 阿里云对象存储   存储图片
 * @author: ling
 * @date: 2022年03月27日
 */

@Component
@Slf4j
public class AlyImage {

    /**
     * 桶名称
     */
    private final String bucketName = "ling-28";

    /**
     * 访问域名
     */
    private final String endpoint = "oss-cn-beijing.aliyuncs.com";

    /**
     * keyId
     */
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId = "LTAI5t9hr8ixKv83J5Dkc9Lp";

    /**
     * 密钥key
     */
    @Value("${aliyun.oss.accessKeySecret}")
    private String secretAccessKey = "PdCI04iwx0lhKPCBXwcUWLGpn2Jrgf";

    @Autowired(required = false)
    private ImageMd5Mapper imageMd5Mapper;

    /**
     * 初始化对象
     *
     * @return
     */
    private AsyncClient init() {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(accessKeyId)
                .accessKeySecret(secretAccessKey)
                .build());

        AsyncClient client = AsyncClient.builder()
                // Region ID  地域
                .region("cn-beijing")
                .credentialsProvider(provider)
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride(endpoint)
                )
                .build();
        return client;
    }

    /**
     * 上传图片对象到阿里云
     *
     * @param folderName 目录名
     * @param file       要上传的文件对象 MultipartFile
     * @return
     * @throws IOException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public String putImage(String folderName, MultipartFile file) throws IOException,
            ExecutionException, InterruptedException {
        //文件目录路径  ==> （统一路径sbbyyds + 要指定的文件夹）
        String filePathName = "sbbyyds/" + folderName + "/";
        //文件转md5码 , 可确保文件重复文件不上传
        String fileMd5 = DigestUtils.md5Hex(file.getInputStream());
        //图片后缀
        String[] split = file.getOriginalFilename().split("\\.");
        //生成文件名  文件Md5 + 文件的后缀
        String fileName = fileMd5 + "." + split[split.length - 1];
        //初始化client对象
        AsyncClient client = init();
        //进行上传
        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket(bucketName)
                .key(filePathName + fileName)
                .body(file.getInputStream())
                .build();
        //上传 返回
        client.putObject(putObjectRequest);
        //上传成功后关闭client对象
        client.close();
        return getFileHttpPath(filePathName + fileName);
    }

    /**
     * 判断文件是否存在
     *
     * @param fileName 文件目录 + 文件名（文件生成的MD5）.后缀
     * @return
     */
    public boolean isExist(String fileName) {
        AsyncClient client = init();
        //查询
        HeadObjectRequest headObjectRequest = HeadObjectRequest.builder()
                .bucket(bucketName)
                .key(fileName)
                .build();
        //返回数据
        CompletableFuture<HeadObjectResponse> response = client.headObject(headObjectRequest);
        try {
            HeadObjectResponse resp = response.get();
            log.info("查看阿里云图片是否存在：" + new Gson().toJson(resp));
            client.close();
            if (resp != null) {
                return true;
            }
        } catch (Exception e) {
            log.warn("在服务器中找不到图片！");
        } finally {
            client.close();
        }
        return false;
    }

    /**
     * 返回阿里云图片完整url
     * @param filePathName  文件目录 + 文件名（文件生成的MD5）.后缀
     * @return
     */
    public String getFileHttpPath(String filePathName) {
        return "https://" + bucketName + "." + endpoint + "/" + filePathName;
    }

    /**
     * 查看文件是否存在(查数据库)、存在返回文件地址、否则返回null
     * @param file: 文件
     * @param folderName  文件夹
     * @author: ling
     * @date: 2022/5/7
     * @Return: java.lang.String 文件地址
     */
    public String imageIsExist(MultipartFile file, String folderName) {
        try {
            if (!file.isEmpty()) {
                //图片Md5
                String fileMd5 = DigestUtils.md5Hex(file.getInputStream());
                //图片后缀
                String[] split = file.getOriginalFilename().split("\\.");
                String suffix = split[split.length - 1];
                //查询图片是否存在
                QueryWrapper<ImagesMd5> objectQueryWrapper = new QueryWrapper<>();
                objectQueryWrapper.eq("image_md5", fileMd5);
                objectQueryWrapper.eq("folder_name", folderName);
                Long aLong = imageMd5Mapper.selectCount(objectQueryWrapper);
                //图片存在、返回地址
                if (aLong > 0) {
                    return getFileHttpPath("sbbyyds/" + folderName + "/" + fileMd5 + "." + suffix);
                } else {
                    //  不存在返回null
                    return null;
                }
            }
            return null;
        } catch (Exception e) {
            log.error("发布文章查询文件是否存在是发生内部错误！");
            log.error("错误为:{}", e.toString());
            return null;
        }
    }

}
